<template>
  <div class="sync-page">
    <el-page-header>
      <template slot="content">
        <h1>数据同步</h1>
        <p>管理npm包数据的同步任务和历史记录</p>
      </template>
    </el-page-header>
    
    <!-- 同步控制面板 -->
    <el-card class="control-panel-card">
      <template slot="header">
        <div class="card-header">
          <span>同步控制</span>
        </div>
      </template>
      
      <div class="sync-controls">
        <div class="sync-status" :class="syncStatusClass">
          <i :class="syncStatusIcon"></i>
          <span>{{ syncStatusText }}</span>
        </div>
        
        <div class="sync-actions">
          <el-button 
            v-if="!isSyncing"
            type="primary" 
            size="large"
            @click="startFullSync"
            :loading="startingSync"
          >
            <i class="el-icon-refresh-left"></i> 执行全量同步
          </el-button>
          <el-button 
            v-if="!isSyncing"
            size="large"
            @click="startIncrementalSync"
            :loading="startingSync"
          >
            <i class="el-icon-refresh"></i> 执行增量同步
          </el-button>
          <el-button 
            v-else
            type="danger" 
            size="large"
            @click="cancelSync"
          >
            <i class="el-icon-stop"></i> 取消同步
          </el-button>
        </div>
        
        <div class="sync-info">
          <p>上次同步时间: {{ lastSyncTime || '从未同步' }}</p>
          <p>同步状态: {{ syncProgressText }}</p>
          <div v-if="isSyncing" class="progress-bar">
            <el-progress :percentage="syncProgress" status="success" />
          </div>
        </div>
      </div>
    </el-card>
    
    <!-- 同步配置 -->
    <el-card class="config-card">
      <template slot="header">
        <div class="card-header">
          <span>同步配置</span>
        </div>
      </template>
      
      <el-form :model="syncConfig" label-width="120px">
        <el-form-item label="同步源URL">
          <el-input v-model="syncConfig.sourceUrl" placeholder="npm registry URL" />
        </el-form-item>
        
        <el-form-item label="同步超时时间">
          <el-input-number 
            v-model="syncConfig.timeoutSeconds"
            :min="30"
            :max="3600"
            label="秒"
          />
        </el-form-item>
        
        <el-form-item label="批量大小">
          <el-input-number 
            v-model="syncConfig.batchSize"
            :min="10"
            :max="1000"
            :step="10"
            label="个/批次"
          />
        </el-form-item>
        
        <el-form-item label="自动同步">
          <el-switch v-model="syncConfig.autoSync" />
        </el-form-item>
        
        <el-form-item 
          v-if="syncConfig.autoSync"
          label="同步频率"
        >
          <el-select v-model="syncConfig.syncFrequency">
            <el-option label="每小时" value="hourly" />
            <el-option label="每天" value="daily" />
            <el-option label="每周" value="weekly" />
            <el-option label="每月" value="monthly" />
          </el-select>
        </el-form-item>
        
        <el-form-item>
          <el-button type="primary" @click="saveConfig">保存配置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    
    <!-- 同步历史记录 -->
    <el-card class="history-card">
      <template slot="header">
        <div class="card-header">
          <span>同步历史记录</span>
          <el-button type="text" size="small" @click="clearHistory">清空历史</el-button>
        </div>
      </template>
      
      <div class="history-filter">
        <el-select 
          v-model="historyFilter"
          placeholder="筛选状态"
          style="width: 150px; margin-right: 16px;"
          @change="loadSyncHistory"
        >
          <el-option label="全部" value="" />
          <el-option label="成功" value="success" />
          <el-option label="失败" value="failed" />
          <el-option label="取消" value="cancelled" />
        </el-select>
        
        <el-date-picker
          v-model="historyTimeRange"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          style="width: 300px;"
          @change="loadSyncHistory"
        />
      </div>
      
      <div v-if="loadingHistory" class="loading-container">
        <el-loading-spinner />
      </div>
      
      <div v-else-if="syncHistory.length === 0" class="empty-state">
        <p>暂无同步历史记录</p>
      </div>
      
      <el-table 
        v-else
        :data="syncHistory"
        style="width: 100%"
        height="400"
      >
        <el-table-column prop="id" label="ID" width="80" />
        <el-table-column prop="type" label="同步类型" width="100">
          <template slot-scope="scope">
            <el-tag 
              :type="scope.row.type === 'full' ? 'primary' : 'info'"
              size="small"
            >
              {{ scope.row.type === 'full' ? '全量' : '增量' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="100">
          <template slot-scope="scope">
            <el-tag 
              :type="getStatusType(scope.row.status)"
              size="small"
            >
              {{ getStatusText(scope.row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="packagesSynced" label="同步包数" width="100" align="right">
          <template slot-scope="scope">
            {{ formatNumber(scope.row.packagesSynced || 0) }}
          </template>
        </el-table-column>
        <el-table-column prop="duration" label="耗时" width="100" align="right">
          <template slot-scope="scope">
            {{ formatDuration(scope.row.duration) }}
          </template>
        </el-table-column>
        <el-table-column prop="startedAt" label="开始时间" width="180" />
        <el-table-column prop="completedAt" label="完成时间" width="180" />
        <el-table-column label="操作" width="120" fixed="right" align="center">
          <template slot-scope="scope">
            <el-button 
              type="text" 
              size="small" 
              @click="viewHistoryDetail(scope.row.id)"
            >
              详情
            </el-button>
          </template>
        </el-table-column>
      </el-table>
      
      <div v-if="syncHistory.length > 0" class="pagination-container">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="currentPage"
          :page-sizes="[10, 20, 50]"
          :page-size="pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="historyTotal"
        />
      </div>
    </el-card>
    
    <!-- 同步详情对话框 -->
    <el-dialog 
      title="同步详情"
      :visible.sync="historyDetailVisible"
      width="800px"
      :modal-append-to-body="false"
      :append-to-body="true"
    >
      <div v-if="loadingDetail" class="loading-container">
        <el-loading-spinner />
      </div>
      
      <div v-else-if="selectedHistory">
        <el-descriptions bordered column="2">
          <el-descriptions-item label="同步ID">{{ selectedHistory.id }}</el-descriptions-item>
          <el-descriptions-item label="同步类型">
            <el-tag 
              :type="selectedHistory.type === 'full' ? 'primary' : 'info'"
              size="small"
            >
              {{ selectedHistory.type === 'full' ? '全量' : '增量' }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="状态">
            <el-tag 
              :type="getStatusType(selectedHistory.status)"
              size="small"
            >
              {{ getStatusText(selectedHistory.status) }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="同步源">{{ selectedHistory.sourceUrl }}</el-descriptions-item>
          <el-descriptions-item label="同步包数">{{ formatNumber(selectedHistory.packagesSynced || 0) }}</el-descriptions-item>
          <el-descriptions-item label="成功包数">{{ formatNumber(selectedHistory.packagesSuccess || 0) }}</el-descriptions-item>
          <el-descriptions-item label="失败包数">{{ formatNumber(selectedHistory.packagesFailed || 0) }}</el-descriptions-item>
          <el-descriptions-item label="耗时">{{ formatDuration(selectedHistory.duration) }}</el-descriptions-item>
          <el-descriptions-item label="开始时间">{{ selectedHistory.startedAt }}</el-descriptions-item>
          <el-descriptions-item label="完成时间">{{ selectedHistory.completedAt || '未完成' }}</el-descriptions-item>
          <el-descriptions-item label="错误信息" v-if="selectedHistory.errorMessage" span="2">
            <div class="error-message">{{ selectedHistory.errorMessage }}</div>
          </el-descriptions-item>
        </el-descriptions>
        
        <!-- 失败包列表 -->
        <div v-if="selectedHistory.packagesFailed > 0" class="failed-packages">
          <h3 style="margin-top: 16px; margin-bottom: 8px;">失败的包</h3>
          <el-table 
            :data="selectedHistory.failedPackages || []"
            style="width: 100%"
            height="200"
          >
            <el-table-column prop="name" label="包名" width="200" />
            <el-table-column prop="error" label="错误原因">
              <template slot-scope="scope">
                <div class="error-tooltip" :title="scope.row.error">
                  {{ truncateText(scope.row.error, 100) }}
                </div>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: 'SyncPage',
  layout: 'default',
  data() {
    return {
      // 同步状态
      isSyncing: false,
      startingSync: false,
      syncProgress: 0,
      syncStatusText: '空闲',
      lastSyncTime: '从未同步',
      syncProgressText: '准备就绪',
      
      // 同步配置
      syncConfig: {
        sourceUrl: 'https://registry.npmjs.org/',
        timeoutSeconds: 300,
        batchSize: 50,
        autoSync: false,
        syncFrequency: 'daily'
      },
      
      // 同步历史
      syncHistory: [],
      historyTotal: 0,
      loadingHistory: false,
      historyFilter: '',
      historyTimeRange: null,
      currentPage: 1,
      pageSize: 10,
      
      // 历史详情
      historyDetailVisible: false,
      selectedHistory: null,
      loadingDetail: false
    }
  },
  async fetch() {
    await this.loadSyncStatus()
    await this.loadSyncConfig()
    await this.loadSyncHistory()
    
    // 启动同步进度轮询
    this.startProgressPolling()
  },
  beforeDestroy() {
    // 停止轮询
    if (this.progressPollingInterval) {
      clearInterval(this.progressPollingInterval)
    }
  },
  computed: {
    syncStatusClass() {
      if (this.isSyncing) return 'status-running'
      if (this.syncStatusText === '成功') return 'status-success'
      if (this.syncStatusText === '失败') return 'status-error'
      return 'status-idle'
    },
    
    syncStatusIcon() {
      if (this.isSyncing) return 'el-icon-loading'
      if (this.syncStatusText === '成功') return 'el-icon-circle-check'
      if (this.syncStatusText === '失败') return 'el-icon-circle-close'
      return 'el-icon-circle-check'
    }
  },
  methods: {
    async loadSyncStatus() {
      try {
        const response = await this.$axios.get('/sync/status')
        this.isSyncing = response.isSyncing
        this.syncProgress = response.progress || 0
        this.syncStatusText = response.statusText || '空闲'
        this.lastSyncTime = response.lastSyncTime || '从未同步'
        this.syncProgressText = response.progressText || '准备就绪'
      } catch (error) {
        this.$message.error('加载同步状态失败：' + error.message)
        // 设置模拟状态
        this.setMockStatus()
      }
    },
    
    async loadSyncConfig() {
      try {
        const response = await this.$axios.get('/sync/config')
        this.syncConfig = { ...this.syncConfig, ...response }
      } catch (error) {
        this.$message.error('加载同步配置失败：' + error.message)
        // 使用默认配置
      }
    },
    
    async saveConfig() {
      try {
        await this.$axios.put('/sync/config', this.syncConfig)
        this.$message.success('配置保存成功')
      } catch (error) {
        this.$message.error('保存配置失败：' + error.message)
      }
    },
    
    async startFullSync() {
      this.$confirm('确定要执行全量同步吗？这可能需要较长时间。', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        try {
          this.startingSync = true
          await this.$axios.post('/sync/start', { type: 'full' })
          this.isSyncing = true
          this.syncStatusText = '同步中'
          this.syncProgressText = '开始同步数据...'
          this.$message.success('全量同步已开始')
        } catch (error) {
          this.$message.error('启动同步失败：' + error.message)
        } finally {
          this.startingSync = false
        }
      }).catch(() => {
        this.$message.info('已取消同步')
      })
    },
    
    async startIncrementalSync() {
      try {
        this.startingSync = true
        await this.$axios.post('/sync/start', { type: 'incremental' })
        this.isSyncing = true
        this.syncStatusText = '同步中'
        this.syncProgressText = '开始增量同步...'
        this.$message.success('增量同步已开始')
      } catch (error) {
        this.$message.error('启动同步失败：' + error.message)
      } finally {
        this.startingSync = false
      }
    },
    
    async cancelSync() {
      this.$confirm('确定要取消当前同步任务吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        try {
          await this.$axios.post('/sync/cancel')
          this.isSyncing = false
          this.syncStatusText = '已取消'
          this.syncProgress = 0
          this.$message.success('同步已取消')
          await this.loadSyncStatus()
        } catch (error) {
          this.$message.error('取消同步失败：' + error.message)
        }
      }).catch(() => {
        this.$message.info('已取消操作')
      })
    },
    
    async loadSyncHistory() {
      this.loadingHistory = true
      try {
        // 构建请求参数
        const params = {
          status: this.historyFilter,
          page: this.currentPage,
          pageSize: this.pageSize
        }
        
        if (this.historyTimeRange && this.historyTimeRange.length === 2) {
          params.startDate = this.historyTimeRange[0]
          params.endDate = this.historyTimeRange[1]
        }
        
        const response = await this.$axios.get('/sync/history', { params })
        this.syncHistory = response.items || []
        this.historyTotal = response.total || 0
      } catch (error) {
        this.$message.error('加载同步历史失败：' + error.message)
        // 设置模拟历史数据
        this.setMockHistoryData()
      } finally {
        this.loadingHistory = false
      }
    },
    
    async clearHistory() {
      this.$confirm('确定要清空所有同步历史记录吗？此操作不可恢复。', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'error'
      }).then(async () => {
        try {
          await this.$axios.delete('/sync/history')
          this.syncHistory = []
          this.historyTotal = 0
          this.$message.success('同步历史已清空')
        } catch (error) {
          this.$message.error('清空历史失败：' + error.message)
        }
      }).catch(() => {
        this.$message.info('已取消操作')
      })
    },
    
    handleSizeChange(size) {
      this.pageSize = size
      this.loadSyncHistory()
    },
    
    handleCurrentChange(current) {
      this.currentPage = current
      this.loadSyncHistory()
    },
    
    async viewHistoryDetail(historyId) {
      this.loadingDetail = true
      try {
        const response = await this.$axios.get(`/sync/history/${historyId}`)
        this.selectedHistory = response
        this.historyDetailVisible = true
      } catch (error) {
        this.$message.error('加载同步详情失败：' + error.message)
        // 设置模拟详情数据
        this.setMockHistoryDetail(historyId)
      } finally {
        this.loadingDetail = false
      }
    },
    
    startProgressPolling() {
      // 每3秒更新一次同步进度
      this.progressPollingInterval = setInterval(async () => {
        if (this.isSyncing) {
          await this.loadSyncStatus()
        }
      }, 3000)
    },
    
    getStatusType(status) {
      switch (status) {
        case 'success': return 'success'
        case 'failed': return 'danger'
        case 'cancelled': return 'warning'
        default: return 'info'
      }
    },
    
    getStatusText(status) {
      switch (status) {
        case 'success': return '成功'
        case 'failed': return '失败'
        case 'cancelled': return '取消'
        case 'running': return '运行中'
        default: return status
      }
    },
    
    formatNumber(num) {
      if (!num) return '0'
      return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
    },
    
    formatDuration(duration) {
      if (!duration) return '0秒'
      
      if (duration < 60) {
        return `${duration}秒`
      } else if (duration < 3600) {
        const minutes = Math.floor(duration / 60)
        const seconds = duration % 60
        return `${minutes}分${seconds}秒`
      } else {
        const hours = Math.floor(duration / 3600)
        const minutes = Math.floor((duration % 3600) / 60)
        const seconds = duration % 60
        return `${hours}时${minutes}分${seconds}秒`
      }
    },
    
    truncateText(text, maxLength) {
      if (!text || text.length <= maxLength) return text
      return text.substring(0, maxLength) + '...'
    },
    
    // 模拟数据方法
    setMockStatus() {
      this.isSyncing = false
      this.syncProgress = 0
      this.syncStatusText = '成功'
      this.lastSyncTime = '2023-06-15 14:30:25'
      this.syncProgressText = '上次同步完成'
    },
    
    setMockHistoryData() {
      const statuses = ['success', 'failed', 'cancelled']
      const types = ['full', 'incremental']
      const now = new Date()
      
      this.syncHistory = Array.from({ length: 15 }, (_, i) => {
        const date = new Date(now)
        date.setDate(date.getDate() - i)
        
        const startDate = new Date(date)
        startDate.setHours(Math.floor(Math.random() * 24))
        startDate.setMinutes(Math.floor(Math.random() * 60))
        
        const duration = Math.floor(Math.random() * 3000) + 60
        const endDate = new Date(startDate)
        endDate.setSeconds(endDate.getSeconds() + duration)
        
        const status = statuses[Math.floor(Math.random() * statuses.length)]
        const type = types[Math.floor(Math.random() * types.length)]
        const packagesSynced = Math.floor(Math.random() * 1000) + 100
        
        return {
          id: `sync-${Date.now()}-${i}`,
          type,
          status,
          packagesSynced,
          duration,
          startedAt: startDate.toLocaleString('zh-CN'),
          completedAt: status !== 'running' ? endDate.toLocaleString('zh-CN') : null
        }
      })
      
      this.historyTotal = 15
    },
    
    setMockHistoryDetail(historyId) {
      this.selectedHistory = {
        id: historyId,
        type: 'full',
        status: 'success',
        sourceUrl: 'https://registry.npmjs.org/',
        packagesSynced: 1245,
        packagesSuccess: 1230,
        packagesFailed: 15,
        duration: 1245,
        startedAt: '2023-06-15 09:15:30',
        completedAt: '2023-06-15 09:36:15',
        errorMessage: null,
        failedPackages: Array.from({ length: 15 }, (_, i) => ({
          name: `failed-package-${i}`,
          error: 'Connection timeout while fetching package metadata'
        }))
      }
      this.historyDetailVisible = true
    }
  }
}
</script>

<style scoped>
.sync-page {
  padding: 24px;
}

.control-panel-card,
.config-card,
.history-card {
  margin-bottom: 24px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* 同步控制样式 */
.sync-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  align-items: center;
  padding: 16px 0;
}

.sync-status {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 500;
}

.sync-status .el-icon {
  margin-right: 8px;
  font-size: 20px;
}

.status-idle {
  background-color: #f0f9ff;
  color: #0369a1;
}

.status-running {
  background-color: #fff7e6;
  color: #c2410c;
}

.status-success {
  background-color: #f0fdf4;
  color: #166534;
}

.status-error {
  background-color: #fef2f2;
  color: #991b1b;
}

.sync-actions {
  display: flex;
  gap: 12px;
}

.sync-info {
  margin-left: auto;
  min-width: 300px;
}

.sync-info p {
  margin: 4px 0;
  color: #666;
}

.progress-bar {
  margin-top: 8px;
}

/* 历史记录样式 */
.history-filter {
  margin-bottom: 16px;
  display: flex;
  align-items: center;
}

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 200px;
}

.empty-state {
  text-align: center;
  padding: 40px;
  color: #8c8c8c;
}

.pagination-container {
  margin-top: 16px;
  display: flex;
  justify-content: flex-end;
}

/* 详情对话框样式 */
.error-message {
  background-color: #fef2f2;
  color: #991b1b;
  padding: 12px;
  border-radius: 4px;
  white-space: pre-wrap;
}

.failed-packages {
  margin-top: 16px;
}

.error-tooltip {
  max-width: 500px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .sync-page {
    padding: 16px;
  }
  
  .sync-controls {
    flex-direction: column;
    align-items: stretch;
  }
  
  .sync-info {
    margin-left: 0;
    min-width: auto;
  }
  
  .history-filter {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  
  .el-pagination {
    display: flex;
    justify-content: center;
  }
}
</style>